package leetcode.slidingwindow.common;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class SlidingWindowUtils {
    public static int minOperations(int[] nums, int x) {
        int iniSum = Arrays.stream(nums).sum();
        if (iniSum < x) {
            return -1;
        } else if (iniSum == x) {
            return nums.length;
        } else {
            int left = -1;
            int right = 0;
            int result = Integer.MAX_VALUE;
            int n = nums.length;
            int preSum = 0;
            int sufSum = iniSum;
            while (true) {
                while (preSum + sufSum > x && right < n) {
                    sufSum = sufSum - nums[right];  // 判断当前窗口对应的题目的解
                    right = right + 1;  // 如果符合题目条件，就一直往窗口添加新元素   窗口的右边界右移-添加新元素
                }
                if (preSum + sufSum == x) {
                    result = Math.min(result, left + 1 + n - right);
                }
                if (preSum >= x) {
                    break;
                }
                // 将窗口的左边界右移 - 删除窗口元素
                left = left + 1;
                preSum = preSum + nums[left];
            }
            return result == Integer.MAX_VALUE ? -1 : result;
        }
    }

    public static int lengthOfLongestSubstringPro(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        if (s.length() == 1) {
            return 1;
        }
        int result = 0;
        // 窗口范围为 [left, right] 闭区间
        int left = 0;
        int right = 0;
        Map<String, Integer> map = new HashMap<>();
        while (right < s.length()) {
            String c = String.valueOf(s.charAt(right));
            Integer beforeIndex = map.get(c);
            map.put(c, right);
            if (beforeIndex != null && beforeIndex >= left) {
                result = Math.max(result, right - left);
                left = beforeIndex + 1;
            }
            right++;
        }
        result = Math.max(result, right - left);
        return result;
    }

    public static int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        if (s.length() == 1) {
            return 1;
        }
        int result = 0;
        // 窗口范围为 [left, right] 闭区间
        int left = 0;
        int right = 0;
        while (left < s.length()) {
            while (right < s.length()) {
                if (!checkWindow(s, left, right)) {
                    break;
                }
                result = Math.max(result, right - left + 1);
                right++;
            }
            left++;
        }
        return result;
    }

    private static boolean checkWindow(String s, int left, int right) {
        if (left == right) {
            return true;
        }
        if (left == right - 1) {
            return s.charAt(left) != s.charAt(right);
        }
        String sub = s.substring(left, right);
        char c = s.charAt(right);
        for (int i = 0; i < sub.length(); i++) {
            if (sub.charAt(i) == c) {
                return false;
            }
        }
        return true;
    }

    public static int findMaxConsecutiveOnes(int[] nums) {
        int left = 0;
        int right = 0;
        boolean flag = false;
        int result = 0;
        while (right <= nums.length - 1) {
            if (nums[right] == 1) {
                if (!flag) {
                    flag = true;
                    left = right;
                }
            } else {
                if (flag) {
                    result = Math.max(result, right - left);
                    flag = false;
                }
            }
            right++;
        }
        if (flag) {
            result = Math.max(result, right - left);
        }
        return result;
    }

    public static int minSubArrayLen(int target, int[] nums) {
        int result = nums.length + 1;
        int left = 0;
        int right = 0;
        int sum = 0;
        while (right <= nums.length) {
            while (right < nums.length && sum < target) {
                sum += nums[right];
                right++;
            }
            if(sum < target){
                break;
            }
            result = Math.min(result, right - left);
            sum -= nums[left];
            left++;
            if(left == nums.length){
                break;
            }
        }
        return result > nums.length ? 0 : result;
    }
}
